import logging, re
from django.shortcuts import render, redirect
from django.contrib.auth import login
from django.views import View
from django import http
from QQLoginTool.QQtool import OAuthQQ
from django.conf import settings
from django_redis import get_redis_connection

from carts.utils import merge_carts_cookies_redis
from meiduo_mall.utils.response_code import RETCODE
from oauth.models import OAuthQQUser
from oauth.utils import generate_access_token
from oauth.utils import check_access_token
from users.models import User

logger = logging.getLogger("django")


# 提供qq登陆扫码界面
class QQAuthURLView(View):
    def get(self, request):
        next = request.GET.get("next")
        # 创建实例对象
        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID,
                        client_secret=settings.QQ_CLIENT_SECRET,
                        redirect_uri=settings.QQ_REDIRECT_URI,
                        state=next)
        login_url = oauth.get_qq_url()
        return http.JsonResponse({"code":RETCODE.OK, "errmsg":"OK", "login_url": login_url})


# 处理qq登陆业务回调逻辑
class QQAuthUserView(View):
    # 返回qq绑定界面
    def get(self, request):

        code = request.GET.get("code")
        if code is None:
            return http.HttpResponseForbidden("缺少必传参数")
        # 创建实例对象
        oauth = OAuthQQ(client_id=settings.QQ_CLIENT_ID,
                        client_secret=settings.QQ_CLIENT_SECRET,
                        redirect_uri=settings.QQ_REDIRECT_URI)
        try:
            # 使用code像服务器请求access
            access_token = oauth.get_access_token(code)
            # 使用access_token 像服务器请求open_id
            openid = oauth.get_open_id(access_token)

        except Exception as e:
            logger.error(e)
            return http.HttpResponseServerError("请求认证OAuth2.0失败")

        # 判断用户是否登陆过
        try:
            oauth_user = OAuthQQUser.objects.get(openid=openid)
        except OAuthQQUser.DoesNotExist:
            # 如果没有绑定
            access_token = generate_access_token(openid)
            context = {"access_token_openid": access_token}
            return render(request, "oauth_callback.html", context)

        else:
            # 如果绑定了美多商城用户
            qq_user = oauth_user.user
            login(request, qq_user)
            # 响应结果
            next = request.GET.get("state")
            response = redirect(next)
            response.set_cookie("username", qq_user.username, max_age=3600)

            # 用户登陆成功，合并cookie购物车到redis购物车
            response = merge_carts_cookies_redis(request=request, user=qq_user, response=response)

            return response

    # 登陆请求界面
    def post(self, request):
        # 接收参数
        mobile = request.POST.get("mobile")
        password = request.POST.get("password")
        sms_code = request.POST.get("sms_code")
        access_token_openid = request.POST.get("access_token_openid")

        # 校验参数
        if not all([mobile, password, sms_code]):
            return http.HttpResponseForbidden("缺少必传参数")
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseForbidden("请输入正确的手机号码")
        if not re.match(r'^[a-zA-Z0-9]{8,20}$', password):
            return http.HttpResponseForbidden("请输入8-20个字符密码")

        # 校验短信验证码
        redis_conn = get_redis_connection("verify_code")
        sms_code_server = redis_conn.get("sms %s" % mobile)
        if sms_code_server is None:
            return render(request, "oauth_callback.html", {"sms_code_errmsg": "无效短信验证码"})
        if sms_code != sms_code_server.decode("utf-8"):
            return render(request, "oauth_callback.html", {"sms_code_errmsg": "输入短信验证错误"})

        # 校验openid
        openid = check_access_token(access_token_openid)
        if openid is None:
            return render(request, "oauth_callback.html", {"openid_errmsg": "无效的openid"})

        # 保存注册数据 存储到tb_users 数据库
        try:
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist:
            user = User.objects.create_user(username=mobile, password=password, mobile=mobile)
        else:
            # 用户存在校验密码
            if not user.check_password(password):
                return render(request, "oauth_callback.html", {"account_errmsg": "用户名或密码错误"})
        # 保存数据到tb_qq_user表中
        try:
            OAuthQQUser.objects.create(openid=openid, user=user)
        except Exception as e:
            logger.error(e)
            render(request, "oauth_callback.html", {"qq_login_errmsg": "QQ登陆失败"})
        # 状态保持
        login(request, user)

        # 获取登陆的跳转界面
        next = request.GET.get("state")
        response = redirect(next)
        response.set_cookie("username", user.username, max_age=3600)

        # 用户登陆成功，合并cookie购物车到redis购物车
        response = merge_carts_cookies_redis(request=request, user=user, response=response)

        return response
